package cn.xy.base.server.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.xy.base.server.dao.SysPermissionDao;
import cn.xy.base.server.po.SysPermission;
import cn.xy.base.server.po.SysRole;
import cn.xy.base.server.service.SysPermissionService;
import cn.xy.base.server.service.SysRoleService;
import cn.xy.base.server.vo.SysPermissionVO;
import cn.xy.commons.cache.CacheManager;
import cn.xy.commons.constant.Consts;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * SysPermission对应的服务类实现
 *
 * @author auto
 */

@Service
public class SysPermissionServiceImpl extends ServiceImpl<SysPermissionDao, SysPermission> implements SysPermissionService {

    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private CacheManager cacheManager;

    @Override
    public SysPermission getByPath(String path) {
        return this.getOne(new LambdaQueryWrapper<SysPermission>().eq(SysPermission::getPath, path));
    }

    @Override
    public List<SysPermissionVO> generateTree(List<SysPermission> list) {
        if (CollUtil.isEmpty(list)) {
            return new ArrayList<>();
        }

        List<SysPermissionVO> tree = new ArrayList<>();
        List<SysPermissionVO> nodes = list.stream().map(SysPermissionVO::new).collect(Collectors.toList());
        for (SysPermissionVO permission : nodes) {
            if (permission.getParentId() == 0) {
                tree.add(permission);
            } else {
                boolean parentIn = false;
                for (SysPermissionVO p : nodes) {
                    if (p.getId() == permission.getParentId()) {
                        parentIn = true;
                        break;
                    }
                }
                if (!parentIn) {
                    tree.add(permission);
                }
            }
        }
        tree.forEach(c -> setChildren(c, nodes));
        return tree;
    }

    @Override
    public List<SysPermission> listBySortDesc(int parentId) {
        LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<>();
        if (parentId > 0) {
            query.eq(SysPermission::getParentId, parentId);
        }
        query.orderByDesc(SysPermission::getSort);
        query.orderByAsc(SysPermission::getId);
        return list(query);
    }


    @Override
    public List<SysPermission> getPermissionListByIdIn(List<Long> permissionIdList) {
        if (CollUtil.isEmpty(permissionIdList)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<SysPermission> queryWrapper = new LambdaQueryWrapper<SysPermission>()
                .in(SysPermission::getId, permissionIdList)
                .orderByDesc(SysPermission::getSort)
                .orderByAsc(SysPermission::getId);
        return this.list(queryWrapper);
    }

    @Override
    public List<SysPermission> listByParentId(int id) {
        LambdaQueryWrapper<SysPermission> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysPermission::getParentId, id);
        return this.list(queryWrapper);
    }

    @Override
    public SysPermission getByKey(String key) {
        return this.getOne(new LambdaQueryWrapper<SysPermission>().eq(SysPermission::getKey, key));
    }

    @Override
    public List<String> keyListByRoleId(int roleId) {
        String key = "RoleKeyList_" + roleId;
        List<String> keyList = cacheManager.get(key);
        if (CollUtil.isNotEmpty(keyList)) {
            return keyList;
        }
        SysRole sysRole = sysRoleService.getById(roleId);
        if (sysRole == null) {
            return new ArrayList<>();
        }
        List<Long> permissionIdList = Arrays.stream(sysRole.getPermissions().split(Consts.COMMA)).map(Long::parseLong).collect(Collectors.toList());
        List<SysPermission> permissionList = this.getPermissionListByIdIn(permissionIdList);
        if (CollUtil.isEmpty(permissionList)) {
            return new ArrayList<>();
        }
        keyList = permissionList.stream().map(SysPermission::getKey).collect(Collectors.toList());
        // 缓存12小时
        cacheManager.set(key, keyList, 12 * 60 * 60);
        return keyList;
    }

    @Override
    public void delKeyListCache(int roleId) {
        String key = "RoleKeyList_" + roleId;
        cacheManager.del(key);
    }

    @Override
    public List<SysPermission> listBySortDesc(int parentId, List<Integer> idList) {
        LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<>();
        if (parentId > 0) {
            query.eq(SysPermission::getParentId, parentId);
        }
        query.in(CollUtil.isNotEmpty(idList), SysPermission::getId, idList);
        query.orderByDesc(SysPermission::getSort);
        query.orderByAsc(SysPermission::getId);
        return list(query);
    }

    private void setChildren(SysPermissionVO parent, List<SysPermissionVO> list) {
        List<SysPermissionVO> children = new ArrayList<>();
        for (Iterator<SysPermissionVO> ite = list.iterator(); ite.hasNext(); ) {
            SysPermissionVO city = ite.next();
            if (city.getParentId() == parent.getId()) {
                children.add(city);
                ite.remove();
            }
        }
        if (children.isEmpty()) {
            return;
        }
        parent.setChildren(children);
        children.forEach(c -> setChildren(c, list));
    }
}
